package com.deuwise.common.exception.handler;

import com.auth0.jwt.exceptions.TokenExpiredException;
import com.deuwise.common.exception.DeuWiseException;
import com.deuwise.common.exception.RException;
import com.deuwise.common.utils.EnumErrorCode;
import com.deuwise.common.utils.R;
import com.deuwise.common.utils.Result;
import com.deuwise.common.utils.authorize.LicenseCode;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.ExpiredCredentialsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authz.AuthorizationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.ServletException;
import javax.validation.ConstraintViolationException;

/**
 * @author  chenwenchao
 * @date 2018-10-05
 * 异常处理器
 * 
 */
@ControllerAdvice()
@ResponseBody
public class ApplicationExceptionHandler  {

    private Logger log = LoggerFactory.getLogger(getClass());

    public final static String ERROR_DEFAULT_PAGE = "error/error";

    /**
     * 处理自定义异常
     */
    @ExceptionHandler(RException.class)
    public R handleRRException(RException e){
        R r = new R();
        r.put("code", e.getCode());
        r.put("msg", e.getMessage());

        return r;
    }

    /**
     * 参数校验异常
     */
    @ExceptionHandler(IllegalArgumentException.class)
    public Result<String> illegalArgumentException(IllegalArgumentException e) {
        return Result.build(EnumErrorCode.illegalArgument.getCode(), e.getMessage());
    }

    /**
     * API异常
     */
    @ExceptionHandler(DeuWiseException.class)
    public Result<String> handleIFastAPIException(DeuWiseException e) {
        if(e.getMessage().equals(EnumErrorCode.apiAuthorizationFailed.getCodeStr())){
            return Result.build(403, "申请码为："+LicenseCode.getApplyCode()+"缺少授权码");
        }
        return getStringResult(e.getMessage());
    }
    @ExceptionHandler(ServletException.class)
    public Result<String> handleServletException(ServletException e) {
        if(e.getMessage().equals(EnumErrorCode.apiAuthorizationFailed.getCodeStr())){
            return Result.build(403, "申请码为："+LicenseCode.getApplyCode()+"缺少授权码");
        }
        return getStringResult(e.getMessage());
    }

    /**
     * 自定义异常
     */
    @ExceptionHandler(AuthorizationException.class)
    public Result<String> handleAuthorizationEx(AuthorizationException e){
        return getStringResult(e.getMessage());
    }
    private Result<String> getStringResult(String message) {
        try {
            int code =0;
            if("The current Subject is not authenticated.  Access denied.".equals(message)){
                code=44004;
                return Result.build(code, EnumErrorCode.getMsgByCode(code));
            }
            else if(message.contains("Subject does not have permission")){
                code=44111;
                return Result.build(code, EnumErrorCode.getMsgByCode(code));
            }
            try {
                code = Integer.parseInt(message);
            }catch (Exception ex){
                return Result.build(44004, EnumErrorCode.getMsgByCode(44004));
            }
            return Result.build(code, EnumErrorCode.getMsgByCode(code));
        } catch (NumberFormatException e1) {
            log.warn("错误码使用错误，异常内容请抛出EnumErrorCode类的枚举值");
            e1.printStackTrace();
            return Result.build(EnumErrorCode.unknowFail.getCode(), EnumErrorCode.unknowFail.getMsg());
        }
    }


    @ExceptionHandler(DuplicateKeyException.class)
    public Result<String> handleDuplicateKeyException(DuplicateKeyException e) {
        return Result.build(EnumErrorCode.duplicateKeyExist.getCode(), EnumErrorCode.duplicateKeyExist.getMsg());
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public Result<String> noHandlerFoundException(NoHandlerFoundException e) {
        return Result.build(EnumErrorCode.pageNotFound.getCode(), EnumErrorCode.pageNotFound.getMsg());
    }

    @ExceptionHandler(TokenExpiredException.class)
    public Result<String> handleExpiredCredentialsException(TokenExpiredException e) {
        return Result.build(EnumErrorCode.apiAuthorizationExpired.getCode(), EnumErrorCode.apiAuthorizationExpired.getMsg());
    }
    @ExceptionHandler(ShiroException.class)
    public Result<String> handleAuthorizationException(ShiroException e) {
        log.error(e.getMessage());
        if(e instanceof IncorrectCredentialsException) {
        	return Result.build(EnumErrorCode.apiAuthorizationFailed.getCode(), EnumErrorCode.apiAuthorizationFailed.getMsg());
        }else if(e instanceof ExpiredCredentialsException) {
        	return Result.build(EnumErrorCode.apiAuthorizationExpired.getCode(), EnumErrorCode.apiAuthorizationExpired.getMsg());
        }else if(e instanceof AuthenticationException) {
            return Result.build(EnumErrorCode.apiAuthorizationLoggedout.getCode(), EnumErrorCode.apiAuthorizationLoggedout.getMsg());
        }

        return Result.build(EnumErrorCode.notAuthorization.getCode(), EnumErrorCode.notAuthorization.getMsg());
    }
    @Value("${spring.servlet.multipart.max-file-size}")
    private  String maxFileSize;
    @ExceptionHandler(Exception.class)
    public Object handleException(Exception e) {
            log.error(e.getMessage());
            if(e instanceof RException){
                return Result.build(EnumErrorCode.unknowFail.getCode(), e.getMessage());
            }
            return Result.build(EnumErrorCode.unknowFail.getCode(), EnumErrorCode.unknowFail.getMsg());

    }
    @ExceptionHandler(ConstraintViolationException.class)
    public  Object handleConstraintViolationException(ConstraintViolationException e){
        return Result.build(201, e.getMessage());
    }

    /**
     * 处理上传异常
     * @param e
     * @return
     */
    @ExceptionHandler(MultipartException.class)
    @ResponseBody
    public Object multipartException(Exception e) {
        log.error(e.getMessage());
        //language=JSON

        if(e.getMessage().contains("Maximum upload size exceeded")){
            return Result.build(EnumErrorCode.unknowFail.getCode(),"文件太大"+"请上传小于"+maxFileSize);
        }
        return Result.build(EnumErrorCode.unknowFail.getCode(), EnumErrorCode.unknowFail.getMsg());



    }

}
